#ifndef _EB0_STATE_MANAGER_H_
#define _EB0_STATE_MANAGER_H_

// StateManager is not a singleton as might be expected because a
// StateManager could be applied to each window. Not that this is
// intended at the moment, but it's worth considering for the future.

// StateManager's are attached to RenderWindows when the window is created
// There may only be one manager per window and they cannot be duplicated

// The StateManager currently assumes you can only add one state or remove one state at a time
// There may be cases where this is not ideal...

#include <EB0/Prereq.h>
#include <stack>
#include <queue>

namespace EB0
{
namespace Managers
{
	class StateManager
	{
		friend class Window::RenderWindow;

	public:
		void pushState(States::GameState* state);
		void popState();
		void popAllStates();
		void changeState(States::GameState* state);

	private:
		typedef std::stack<States::GameState*> GameStateStack;
		typedef std::vector<States::GameState*> GameStateVector;

		StateManager(Window::RenderWindow* window);
		~StateManager();

		void update(float dt = 0.0f); // to be called by the RenderWindow only

		static void loadThread(void* statemgr); //sf::Thread requires void* for all incoming data
		static void unloadThread(void* statemgr); // so we'll just have to convert it to StateManager*

		void removeAllStates(); // called via destructor, which happens on window close or shutdown

		sf::Thread* mThread; // thread launcher
		bool mThreadBusy; // indicates if either of the load or unload threads are busy

		GameStateStack mStates;
		GameStateVector mPending; // a null pointer means pop the state
		States::GameState* mPendingState; // state being loaded or unloaded
		Window::RenderWindow* mWindow;

		mutable sf::Mutex mMutex;
	};
} // namespace Managers
}

#endif // _EB0_STATE_MANAGER_H_